﻿using System;
using System.Collections.Generic;
using System.Linq;
using SoftSource.Reactive;
using SoftSource.Ria;
using SoftSource.Timecard.Web.Data;

namespace SoftSource.Timecard.Model
{
    public sealed partial class AdministratorModel : IModelQueries
    {
        #region Parameter-less

        public IObservable<Unit> LoadData()
        {
            var load = from pre in this.PreLoadQuery
                       from data in this.LoadDataQuery
                       from resource in Observable.Start(this.SetResources)
                       select data;
            return load.Once();
        }

        public IObservable<IEnumerable<LastEntry>> GetLatestEntries()
        {
            return this.entries.Query(this.entries.GetLatestEntryQuery());
        }

        public IObservable<IEnumerable<EntryLog>> GetFlaggedEntries()
        {
            return this.entries.Query(this.entries.GetFlaggedEntriesQuery());
        }

        public IObservable<IEnumerable<EntryLog>> GetEntriesPastProjectDueDate()
        {
            return this.entries.Query(this.entries.GetEntriesPastDueDateQuery());
        }

        public IObservable<IEnumerable<EntryLog>> GetEntriesPriorToLastBillingDate()
        {
            return this.entries.Query(this.entries.GetEntriesPriorToLastBillingDateQuery());
        }

        public IObservable<IEnumerable<ProjectSummary>> GetProjectsWithInvalidManagers()
        {
            var load = from preLoad in this.PreLoadQuery
                       select from p in App.Model.ProjectSummaries.Entities
                              join u in App.Model.UserSummaries.Entities on p.ManagerUserID equals u.UserID
                              where
                              p.StatusID == ProjectStatus.Active &&
                              (!u.IsActive ||
                              (u.RoleID != Role.Administrator && u.RoleID != Role.ProjectManager))
                              select p;
            return load;
        }

        #endregion Parameter-less

        #region Parametered

        public IObservable<User> LoadDataForUser(int userID)
        {
            var loadUser = from loadData in Observable.ForkJoin(
                                App.Model.Roles.Load,
                                App.Model.UserTypes.Load)
                           from user in this.users.QuerySingleOrDefault(this.users.GetUserByIDQuery(userID))
                           select user;

            return loadUser;
        }

        public IObservable<Project> LoadDataForProject(int projectID)
        {
            var loadProject = from loadData in Observable.ForkJoin(
                                  App.Model.ProjectTypes.Load,
                                  App.Model.RevenueTypes.Load,
                                  App.Model.ProjectStatuses.Load,
                                  App.Model.BillingFrequencies.Load,
                                  this.projects.Execute(this.projects.GetProjectCategoriesForProjectQuery(projectID)),
                                  this.projects.Execute(this.projects.GetProjectMembersForProjectQuery(projectID)))
                                  .ToUnit()
                              from p in this.projects.QuerySingleOrDefault(this.projects.GetProjectByIDQuery(projectID))
                              select p;

            return loadProject;
        }

        public IObservable<DateTime> GetProjectCreationDate(int projectID)
        {
            return DomainContextExtensions.AsObservable(() => this.utilities.GetProjectCreationDate(projectID))
                .Where(obj => obj is DateTime)
                .Select(obj => (DateTime)obj);
        }

        public IObservable<IEnumerable<ProjectMember>> GetProjectMembersForUser(int userID)
        {
            return this.projects.Query(this.projects.GetProjectMembersForUserQuery(userID));
        }

        public IObservable<IEnumerable<EntrySummary>> GetUtilizationSummaries(DateTime startDate, DateTime endDate)
        {
            return this.entries.Query(this.entries.GetUtilizationSummariesQuery(startDate, endDate));
        }

        public IObservable<IEnumerable<EntryLog>> MarkEntriesAsBilled(int projectID, DateTime? startDate, DateTime endDate)
        {
            return this.entries.Query(this.entries.MarkEntriesAsBilledQuery(projectID, startDate, endDate));
        }

        public IObservable<Unit> SendReminders(
            string password,
            IEnumerable<int> userIDs,
            string message)
        {
            return DomainContextExtensions
                .AsObservable(() => this.utilities.SendReminders(password, userIDs, message))
                .ToUnit();
        }

        public IObservable<Unit> SendEmail(
            string password,
            IEnumerable<int> toUserIDs,
            IEnumerable<int> ccUserIDs,
            string subject,
            string message,
            bool seperateToAddresses)
        {
            return DomainContextExtensions
                .AsObservable(() => this.utilities.SendEmail(password, subject, message, toUserIDs, ccUserIDs, seperateToAddresses))
                .ToUnit();
        }

        public IObservable<IEnumerable<EntryLog>> GetFilteredEntries(
            int? projectID,
            int? userID,
            DateTime? startDate,
            DateTime? endDate)
        {
            return this.entries.Query(this.entries.GetFilteredEntryLogsQuery(
                projectID,
                userID,
                startDate,
                endDate));
        }

        #endregion Parametered
    }
}
